package com.lefull.lefullbase.utils.OkGoHelper;

import com.google.gson.stream.JsonReader;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class SafeJsonReader extends JsonReader {

    public SafeJsonReader(Reader in) {
        super(in);
    }

    @Override
    public int nextInt() throws IOException {
        try {
            return super.nextInt();
        } catch (Exception e) {
            return 0;
        }
    }

    @Override
    public long nextLong() throws IOException {
        try {
            return super.nextLong();
        } catch (Exception e) {
            return 0;
        }
    }

    @Override
    public double nextDouble() throws IOException {
        try {
            return super.nextDouble();
        } catch (Exception e) {
            return 0.0;
        }
    }

    @Override
    public boolean nextBoolean() throws IOException {
        try {
            return super.nextBoolean();
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public String nextString() throws IOException {
        try {
            return super.nextString();
        } catch (Exception e) {
            return "";
        }
    }

    @Override
    public String nextName() throws IOException {
        try {
            return super.nextName();
        } catch (Exception e) {
            return "";
        }
    }

    @Override
    public void nextNull() throws IOException {
        try {
            super.nextNull();
        } catch (Exception e) {

        }
    }

    @Override
    public void beginArray() throws IOException {
        try {
            super.beginArray();
        } catch (Exception e) {
            try {
                Method push = JsonReader.class.getDeclaredMethod("push", int.class);
                push.setAccessible(true);

                Class JsonScope = Class.forName("com.google.gson.stream.JsonScope");
                Field emptyArray = JsonScope.getDeclaredField("EMPTY_ARRAY");
                emptyArray.setAccessible(true);
                push.invoke(this, emptyArray.getInt(null));

                Field pathIndices = JsonReader.class.getDeclaredField("pathIndices");
                pathIndices.setAccessible(true);

                Field stackSize = JsonReader.class.getDeclaredField("stackSize");
                stackSize.setAccessible(true);

                Object array = pathIndices.get(this);
                Array.set(array, stackSize.getInt(this) - 1, 0);
                pathIndices.set(this, array);

                Field peeked = JsonReader.class.getDeclaredField("peeked");
                peeked.setAccessible(true);

                Field peekedEndArray = JsonReader.class.getDeclaredField("PEEKED_END_ARRAY");
                peekedEndArray.setAccessible(true);
                peeked.set(this, peekedEndArray.getInt(null));

            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    @Override
    public void endArray() throws IOException {
        try {
            super.endArray();
        } catch (Exception e) {
            try {
                Field stackSize = JsonReader.class.getDeclaredField("stackSize");
                stackSize.setAccessible(true);
                stackSize.set(this, stackSize.getInt(this) - 1);

                Field pathIndices = JsonReader.class.getDeclaredField("pathIndices");
                pathIndices.setAccessible(true);
                Object array = pathIndices.get(this);

                Integer original = (Integer) Array.get(array, stackSize.getInt(this) - 1);
                Array.set(array, stackSize.getInt(this) - 1, original + 1);
                pathIndices.set(this, array);

                Field peeked = JsonReader.class.getDeclaredField("peeked");
                peeked.setAccessible(true);
                Field peekedNone = JsonReader.class.getDeclaredField("PEEKED_NONE");
                peekedNone.setAccessible(true);
                peeked.set(this, peekedNone.getInt(null));
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    @Override
    public void beginObject() throws IOException {
        try {
            super.beginObject();
        } catch (Exception e) {
            try {
                Method push = JsonReader.class.getDeclaredMethod("push", int.class);
                push.setAccessible(true);

                Class JsonScope = Class.forName("com.google.gson.stream.JsonScope");
                Field emptyObject = JsonScope.getDeclaredField("EMPTY_OBJECT");
                emptyObject.setAccessible(true);
                push.invoke(this, emptyObject.getInt(null));

                Field peeked = JsonReader.class.getDeclaredField("peeked");
                peeked.setAccessible(true);

                Field peekedEndObject = JsonReader.class.getDeclaredField("PEEKED_END_OBJECT");
                peekedEndObject.setAccessible(true);
                peeked.set(this, peekedEndObject.getInt(null));
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    @Override
    public void endObject() throws IOException {
        try {
            super.endObject();
        } catch (Exception e) {
            try {
                Field stackSize = JsonReader.class.getDeclaredField("stackSize");
                stackSize.setAccessible(true);
                stackSize.set(this, stackSize.getInt(this) - 1);

                Field pathNames = JsonReader.class.getDeclaredField("pathNames");
                pathNames.setAccessible(true);

                Object pathNamesArray = pathNames.get(this);
                Array.set(pathNamesArray, stackSize.getInt(this), null);
                pathNames.set(this, pathNamesArray);

                Field pathIndices = JsonReader.class.getDeclaredField("pathIndices");
                pathIndices.setAccessible(true);
                Object pathIndicesArray = pathIndices.get(this);

                Integer original = (Integer) Array.get(pathIndicesArray, stackSize.getInt(this) - 1);
                Array.set(pathIndicesArray, stackSize.getInt(this) - 1, original + 1);
                pathIndices.set(this, pathIndicesArray);

                Field peeked = JsonReader.class.getDeclaredField("peeked");
                peeked.setAccessible(true);
                Field peekedNone = JsonReader.class.getDeclaredField("PEEKED_NONE");
                peekedNone.setAccessible(true);
                peeked.set(this, peekedNone.getInt(null));
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    @Override
    public boolean hasNext() throws IOException {
        try {
            return super.hasNext();
        } catch (Exception e) {
            return false;
        }
    }
}
